<?php
/* ========================================================================
 * ppphp核心类
 * 实现以下几个功能
 * 类自动加载
 * 启动框架
 * 引入模型
 * 引入视图
 * ======================================================================== */
class ppphp {
    /**
     * classMap用于存放已经加载过的类文件,下次加载的时候直接返回
     */
    public static $classMap = array();
    /**
     * model用于存放已经加载的model模型,下次加载时直接返回
     */
    public $model;
    /**
     * 视图赋值
     */
    public $assign;

    /**
     * 自动加载类
     * 先判断类是否已经加载,如果加载过直接从classMap中返回,如果没有加载的话,先到CORE中查找,再在整个框架中进行查找
     * @param $class 需要加载的类,需要带上命名空间
     * @return object
     */
    public static function load($class)
    {
        if(isset($classMap[$class])) {
            return true;
        } else {
            $class = str_replace('\\','/',trim($class,'\\'));
            if(is_file(CORE.$class.'.php')){
                include_once CORE.$class.'.php';
                self::$classMap[] = $class;
            } else {
                if(is_file(PPPHP.'/'.$class.'.php')) {
                    include_once PPPHP.'/'.$class.'.php';
                    self::$classMap[] = $class;
                }
            }
        }
    }

    /**
     * 框架启动方法,完成了两件事情
     * 1.加载route解析当前URL
     * 2.找到对应的模块、控制以及方法,并运行
     */
    public static function run()
    {
        $r = new \ppphp\route();
        define('APP', PPPHP.'/app/'.$r->module.'/');
        define('MODULE', $r->module);
        \ppphp\log::init();
        $ctrlClass ='\\'.'app'. '\\'.MODULE.'\ctrl\\'.$r->ctrl.'Ctrl';
        $action = $r->action;
        $ctrlFile = APP.'ctrl/'.$r->ctrl.'Ctrl.php';
        if(is_file($ctrlFile)) {
            include $ctrlFile;
            $ctrl = new $ctrlClass();
            if(method_exists($ctrl, $action))
            {
                $ctrl->$action();
            }
            else
            {
                if(is_file(APP.'views/500.html'))
                {
                    $ctrl = new ppphp();
                    $ctrl->assign('msg','无法解析:'.$action);
                    $ctrl->_500();
                }
                else
                {
                    throw new Exception('无法解析:'.$action);
                }
            }
        } else {
            if(is_file(APP.'views/500.html'))
            {
                $ctrl = new ppphp();
                $ctrl->assign('msg','控制器:'.$ctrlClass.'不存在!');
                $ctrl->_500();
            }
            else
            {
                throw new Exception('控制器:'.$ctrlClass.'不存在!');
            }
        }
    }
    
    /**
     * 为模板对象赋值
     */
    public function assign($name,$data)
    {
        $this->assign[$name] = $data;
    }

    /**
     * 用于在控制器中加载一个模板文件
     */
    public function display($file)
    {
        if(!is_file(APP.'views/'.$file)) 
        {
            if(is_file(APP.'views/404.html'))
            {
                $this->assign('msg','模板文件:'.'views/'.$file.' 不存在!');    
                $file='404.html';
            }
            else
            {
                throw new Exception('模板文件:'.'views/'.$file.' 不存在!');
            }
        }
        Twig_Autoloader::register();
        $loader = new Twig_Loader_Filesystem(APP . 'views/');
        $twig = new Twig_Environment($loader,[
            'cache' => PPPHP.'/log/twig_cache',
            'debug' => DEBUG,
        ]);
        $twig->getExtension('Twig_Extension_Core')->setDateFormat('Y/m/d', '%d days');
        //$twig->getExtension('Twig_Extension_Core')->setTimezone('Asina/ShangHai');

        $template = $twig->loadTemplate($file);
        $template->display($this->assign?$this->assign:[]);
    }

    /**
     * 404
     */
    public function _404()
    {
        $this->display('404.html');
    }

    /**
     * 500
     */
    public function _500()
    {
        $this->display('500.html');
    }
}